package uk.ac.bbk.dcs.pakdd2014.train;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

import uk.ac.bbk.dcs.pakdd2014.Date;
import uk.ac.bbk.dcs.pakdd2014.Parser;
import uk.ac.bbk.dcs.pakdd2014.RepairDate;
import uk.ac.bbk.dcs.pakdd2014.SalesDate;
import uk.ac.bbk.dcs.pakdd2014.Distribution;

public class Prepare {

	private static int MIN_YEAR = 2003;
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		HashSet<Integer> seenModules = new HashSet<Integer>();
		HashSet<Integer> seenComponents = new HashSet<Integer>();
		HashSet<SalesDate> sales=Parser.parseST();
		HashSet<RepairDate> repairs=Parser.parseRT();
		Distribution allModuleDistribution = new Distribution();
		HashMap<Integer,Distribution> moduleLifeDistributions = new HashMap<Integer,Distribution>();
		Distribution allComponentDistribution = new Distribution();
		HashMap<Integer,HashMap<Date,Integer>> componentCumSalesLookup = new HashMap<Integer,HashMap<Date,Integer>>();
		HashMap<Integer,HashMap<Date,Integer>> moduleCumSalesLookup = new HashMap<Integer,HashMap<Date,Integer>>();
		for(SalesDate s: sales)
		{
			seenModules.add(s.getModule());
			seenComponents.add(s.getComponent());

			if(!componentCumSalesLookup.containsKey(s.getComponent()))
			{
				componentCumSalesLookup.put(s.getComponent(), new HashMap<Date,Integer>());
			}
			if(!moduleCumSalesLookup.containsKey(s.getModule()))
			{
				moduleCumSalesLookup.put(s.getModule(), new HashMap<Date,Integer>());
			}
			HashMap<Date,Integer> componentAcc = componentCumSalesLookup.get(s.getComponent());
			HashMap<Date,Integer> moduleAcc = moduleCumSalesLookup.get(s.getModule());
			componentAcc.put(new Date(2001,01), 0);
			moduleAcc.put(new Date(2001,01), 0);
			for(Entry<Date,Integer> d: s.getSold().entrySet())
			{
				if(!componentAcc.containsKey(d.getKey()))
				{
					componentAcc.put(d.getKey(),0);
				}
				if(!moduleAcc.containsKey(d.getKey()))
				{
					moduleAcc.put(d.getKey(),0);
				}
				for(Entry<Date,Integer> d2 : componentAcc.entrySet())
				{
					if(d.getKey().differenceDate(d2.getKey()) >= 0)
					{
						int current = d2.getValue();
						componentAcc.put(d2.getKey(), current + d.getValue());
					}
				}
				for(Entry<Date,Integer> d2 : moduleAcc.entrySet())
				{
					if(d.getKey().differenceDate(d2.getKey()) >= 0)
					{
						int current = d2.getValue();
						moduleAcc.put(d2.getKey(), current + d.getValue());
					}
				}
			}
		}

		HashMap<Integer,Distribution> componentLifeDistributions = new HashMap<Integer,Distribution>();
		for(RepairDate r : repairs)
		{
			if(!moduleLifeDistributions.containsKey(r.getModule()))
			{
				moduleLifeDistributions.put(r.getModule(), new Distribution());		
			}
			if(!componentLifeDistributions.containsKey(r.getComponent()))
			{
				componentLifeDistributions.put(r.getComponent(), new Distribution());		
			}
			Distribution m = moduleLifeDistributions.get(r.getModule());
			Distribution c = componentLifeDistributions.get(r.getComponent());
			seenModules.add(r.getModule());
			seenComponents.add(r.getComponent());
			for(Date sold : r.getRepaired().keySet())
			{
				for(Date repaired: r.getRepaired().get(sold).keySet())
				{
					int qty = r.getRepaired().get(sold).get(repaired);
					int age = repaired.differenceDate(sold);
					for(int i = 0; i < qty; i++)
					{
						/*m.include(age);
						c.include(age);
						allModuleDistribution.include(age);
						allComponentDistribution.include(age);*/
					}
				}
			}
		}
		PrintWriter trainingSet = new PrintWriter("datasets/trainingSet.csv", "UTF-8");
		for(RepairDate r : repairs)
		{
			int component = r.getComponent();
			int module = r.getModule();
			double componentMean = componentLifeDistributions.get(component).mean();
			double moduleMean = moduleLifeDistributions.get(module).mean();
			double componentVar = componentLifeDistributions.get(component).var();
			double moduleVar = moduleLifeDistributions.get(module).var();
			for(Date sold : r.getRepaired().keySet())
			{
				for(Date repaired : r.getRepaired().get(sold).keySet())
				{
					Date search = repaired.clone();
					while(!componentCumSalesLookup.get(component).containsKey(search))
						search.dec();
					int componentsSoldSoFar = componentCumSalesLookup.get(component).get(search);
					search = repaired.clone();
					while(!moduleCumSalesLookup.get(module).containsKey(search)) 
						search.dec();
					int modulesSoldSoFar = moduleCumSalesLookup.get(module).get(search);
					int age = repaired.differenceDate(sold);
					int qty = r.getRepaired().get(sold).get(repaired);
					String line =
						component + "," +
						module + "," +
						(repaired.getYear() - MIN_YEAR) + "," +
						repaired.getMonth() + "," +
						(sold.getYear() - MIN_YEAR)+ "," +
						sold.getMonth() + "," +
						componentMean + "," +
						componentVar + "," +
						componentsSoldSoFar + "," +
						moduleMean + "," +
						moduleVar + "," +
						modulesSoldSoFar + "," +
						age + "," +
						qty;
					trainingSet.println(line);
				}
			}
		}
		trainingSet.close();
	}

}
